improve format/filter vector validation. (#427)
authortsteven4 <13596209+tsteven4@users.noreply.github.com>
Mon, 2 Dec 2019 01:16:09 +0000 (18:16 -0700)
committerGitHub <noreply@github.com>
Mon, 2 Dec 2019 01:16:09 +0000 (18:16 -0700)
defs.h
filter_vecs.cc
filterdefs.h
main.cc
vecs.cc

diff --git a/defs.h b/defs.h
index 2c1bb0ee37e3344e73f1eee0cc208ff2c6175eb8..5dee01c2fddd58e2a0d0ddaf3ce6e22bd4569da9 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -983,8 +983,8 @@ void setshort_is_utf8(short_handle h, int is_utf8);
 #define ARGTYPE_TYPEMASK 0x00000fffU
 #define ARGTYPE_FLAGMASK 0xfffff000U
 
-#define ARG_NOMINMAX NULL, NULL
-#define ARG_TERMINATOR {0, 0, 0, 0, 0, ARG_NOMINMAX, NULL}
+#define ARG_NOMINMAX nullptr, nullptr
+#define ARG_TERMINATOR {nullptr, nullptr, nullptr, nullptr, 0, ARG_NOMINMAX, nullptr}
 
 struct arglist_t {
   const char* argstring;
@@ -1072,7 +1072,8 @@ void assign_option(const char* vecname, arglist_t* ap, const char* val);
 void disp_vec_options(const char* vecname, arglist_t* ap);
 void disp_vecs();
 void disp_vec(const char* vecname);
-int validate_formats();
+bool validate_args(const char* vecname, arglist_t* ap);
+bool validate_formats();
 void init_vecs();
 void exit_vecs();
 void disp_formats(int version);
index 00476b6d8690070c86775d4e8e905d457ebfa5f9..aca6120a239330ee6d5cf129a79c484bf29bbfce 100644 (file)
@@ -43,7 +43,6 @@
 #include "gbversion.h"
 #include "inifile.h"
 
-#include <QtCore/QList>        // for QList
 #include <QtCore/QString>      // for QString
 #include <QtCore/QStringList>  // for QStringList
 #include <QtCore/QVector>      // for QVector<>::iterator, QVector
@@ -316,12 +315,6 @@ disp_filter_vec(const char* vecname)
   }
 }
 
-static bool
-alpha(const fl_vecs_t& a, const fl_vecs_t& b)
-{
-  return case_ignore_strcmp(a.desc, b.desc) < 0;
-}
-
 static
 void disp_help_url(const fl_vecs_t& vec, arglist_t* arg)
 {
@@ -362,6 +355,11 @@ void
 disp_filters(int version)
 {
   auto sorted_filter_vec_list = filter_vec_list;
+
+  auto alpha = [](const fl_vecs_t& a, const fl_vecs_t& b)->bool {
+    return case_ignore_strcmp(a.desc, b.desc) < 0;
+  };
+
   std::sort(sorted_filter_vec_list.begin(), sorted_filter_vec_list.end(), alpha);
 
   switch (version) {
@@ -380,3 +378,22 @@ disp_filters(int version)
     ;
   }
 }
+
+static bool
+validate_filter_vec(const fl_vecs_t& vec)
+{
+  bool ok = validate_args(vec.name, vec.vec->get_args());
+
+  return ok;
+}
+
+bool validate_filters()
+{
+  bool ok = true;
+
+  for (const auto& vec : filter_vec_list) {
+    ok = validate_filter_vec(vec) && ok;
+  }
+
+  return ok;
+}
index 4cfc5b4f555487718c4dfcdbe560a9f0f284ee72..cfed0ed94c586ddc299f10c78ef49b37b71bc22f 100644 (file)
@@ -50,10 +50,10 @@ struct filter_vecs_t {
 Filter* find_filter_vec(const char* const, const char**);
 void free_filter_vec(Filter*);
 void disp_filters(int version);
-void disp_filter(const char* vecname);
 void disp_filter_vec(const char* vecname);
 void disp_filter_vecs();
 void init_filter_vecs();
 void exit_filter_vecs();
+bool validate_filters();
 
 #endif // FILTERDEFS_H_INCLUDED_
diff --git a/main.cc b/main.cc
index f87a31fbd2fe9972cbfe537d80ea885aa289bd81..fd85021be8465369ee46d19f36a70c193bbe72f0 100644 (file)
--- a/main.cc
+++ b/main.cc
@@ -65,14 +65,11 @@ public:
   QStringList qargs;
 
 public:
-  QargStackElement()
-    = default;
+  QargStackElement() = default;
 
-  QargStackElement(int p_argn, const QStringList& p_qargs)
-  {
-    argn = p_argn;
-    qargs = p_qargs;
-  }
+  QargStackElement(int p_argn, const QStringList& p_qargs) :
+    argn{p_argn}, qargs{p_qargs}
+  {}
 };
 
 static QStringList
@@ -203,7 +200,6 @@ signal_handler(int sig)
 static int
 run(const char* prog_name)
 {
-  int c;
   int argn;
   ff_vecs_t* ivecs = nullptr;
   ff_vecs_t* ovecs = nullptr;
@@ -262,7 +258,7 @@ run(const char* prog_name)
       return 0;
     }
 
-    c = qargs.at(argn).size() > 1 ? qargs.at(argn).at(1).toLatin1() : '\0';
+    int c = qargs.at(argn).size() > 1 ? qargs.at(argn).at(1).toLatin1() : '\0';
 
     if (qargs.at(argn).size() > 2) {
       opt_version = qargs.at(argn).at(2).digitValue();
@@ -453,8 +449,11 @@ run(const char* prog_name)
     /*
      * Undocumented '-@' option for test.
      */
-    case '@':
-      return validate_formats();
+    case '@': {
+      bool format_ok = validate_formats();
+      bool filter_ok = validate_filters();
+      return (format_ok && filter_ok)? 0 : 1;
+    }
 
     /*
      * Undocumented '-vs' option for GUI wrappers.
diff --git a/vecs.cc b/vecs.cc
index 578f2326487a8890c9aa17d306f47f6dfbf36c6b..4cd6b8078c707192d4d57173e581e9f409a582d0 100644 (file)
--- a/vecs.cc
+++ b/vecs.cc
 #include "defs.h"
 #include "gbversion.h"          // for WEB_DOC_DIR
 #include "inifile.h"            // for inifile_readstr
+#include "src/core/logging.h"   // for Warning
 #include "xcsv.h"               // for XcsvFile, xcsv_file, xcsv_read_internal_style, xcsv_setup_internal_style
 
 
-#define MYNAME "vecs.c"
+#define MYNAME "vecs"
 
 struct vecs_t {
   ff_vecs_t* vec;
@@ -1110,7 +1111,7 @@ init_vecs()
   }
 }
 
-int
+static int
 is_integer(const char* c)
 {
   return isdigit(c[0]) || ((c[0] == '+' || c[0] == '-') && isdigit(c[1]));
@@ -1125,11 +1126,6 @@ exit_vecs()
     }
     if (vec.vec->args) {
       for (auto ap = vec.vec->args; ap->argstring; ap++) {
-        if (ap->defaultvalue &&
-            (ap->argtype == ARGTYPE_INT) &&
-            ! is_integer(ap->defaultvalue)) {
-          warning("%s: not an integer\n", ap->argstring);
-        }
         if (ap->argvalptr) {
           xfree(ap->argvalptr);
           *ap->argval = ap->argvalptr = nullptr;
@@ -1296,7 +1292,7 @@ find_vec(const char* vecname, const char** opts)
     }
 
 #if CSVFMTS_ENABLED
-    // xcsv_setup_internal_style( NULL );
+    // xcsv_setup_internal_style( nullptr );
 #endif // CSVFMTS_ENABLED
     xfree(v);
     vec.vec->name = vec.name;  /* needed for session information */
@@ -1411,22 +1407,12 @@ get_option(const char* iarglist, const char* argname)
   return rval;
 }
 
-/*
- *  Display the available formats in a format that's easy for humans to
- *  parse for help on available command line options.
- */
-static bool
-alpha(const vecs_t& a, const vecs_t& b)
-{
-  return case_ignore_strcmp(a.desc, b.desc) < 0;
-}
-
 /*
  * Smoosh the vecs list and style lists together and sort them
  * alphabetically.  Returns an allocated copy of a style_vecs_array
  * that's populated and sorted.
  */
-QVector<vecs_t>
+static QVector<vecs_t>
 sort_and_unify_vecs()
 {
   QVector<vecs_t> svp;
@@ -1480,6 +1466,14 @@ sort_and_unify_vecs()
     svp.append(uvec);
   }
 
+  /*
+   *  Display the available formats in a format that's easy for humans to
+   *  parse for help on available command line options.
+   */
+  auto alpha = [](const vecs_t& a, const vecs_t& b)->bool {
+    return case_ignore_strcmp(a.desc, b.desc) < 0;
+  };
+
   /* Now that we have everything in an array, alphabetize them */
   std::sort(svp.begin(), svp.end(), alpha);
 
@@ -1660,74 +1654,101 @@ disp_formats(int version)
   }
 }
 
+bool validate_args(const char* vecname, arglist_t* ap)
+{
+  bool ok = true;
+
+  for (; ap && ap->argstring; ap++) {
+    if (ap->argtype == ARGTYPE_INT) {
+      if (ap->defaultvalue &&
+          ! is_integer(ap->defaultvalue)) {
+        Warning() << vecname << "Int option" << ap->argstring << "default value" << ap->defaultvalue << "is not an integer.";
+        ok = false;
+      }
+      if (ap->minvalue &&
+          ! is_integer(ap->minvalue)) {
+        Warning() << vecname << "Int option" << ap->argstring << "minimum value" << ap->minvalue << "is not an integer.";
+        ok = false;
+      }
+      if (ap->maxvalue &&
+          ! is_integer(ap->maxvalue)) {
+        Warning() << vecname << "Int option" << ap->argstring << "maximum value" << ap->maxvalue << "is not an integer.";
+        ok = false;
+      }
+    }
+  }
+
+  return ok;
+}
+
 static bool
 validate_vec(const vecs_t& vec)
 {
-  bool ok = true;
+  bool ok = validate_args(vec.name, vec.vec->args);
 
   if (!((vec.vec->cap[0]|vec.vec->cap[1]|vec.vec->cap[2]) & ff_cap_write)) {
     if (vec.vec->wr_init != nullptr) {
-      printf("ERROR no write capability but non-null wr_init %s\n", vec.name);
+      Warning() << "ERROR no write capability but non-null wr_init %s\n" << vec.name;
       ok = false;
     }
   }
   if (!((vec.vec->cap[0]|vec.vec->cap[1]|vec.vec->cap[2]) & ff_cap_read)) {
     if (vec.vec->rd_init != nullptr) {
-      printf("ERROR no read capbility but non-null rd_init %s\n", vec.name);
+      Warning() << "ERROR no read capability but non-null rd_init %s\n" << vec.name;
       ok = false;
     }
   }
   if ((vec.vec->cap[0]|vec.vec->cap[1]|vec.vec->cap[2]) & ff_cap_write) {
     if (vec.vec->wr_init == nullptr) {
-      printf("ERROR write capability but null wr_init %s\n", vec.name);
+      Warning() << "ERROR write capability but null wr_init %s\n" << vec.name;
       ok = false;
     }
   }
   if ((vec.vec->cap[0]|vec.vec->cap[1]|vec.vec->cap[2]) & ff_cap_read) {
     if (vec.vec->rd_init == nullptr) {
-      printf("ERROR read capability but null rd_init %s\n", vec.name);
+      Warning() << "ERROR read capability but null rd_init %s\n" << vec.name;
       ok = false;
     }
   }
 
   if (vec.vec->wr_init != nullptr) {
     if (vec.vec->write == nullptr) {
-      printf("ERROR nonnull wr_init but null write %s\n", vec.name);
+      Warning() << "ERROR nonnull wr_init but null write %s\n" << vec.name;
       ok = false;
     }
     if (vec.vec->wr_deinit == nullptr) {
-      printf("ERROR nonnull wr_init but null wr_deinit %s\n", vec.name);
+      Warning() << "ERROR nonnull wr_init but null wr_deinit %s\n" << vec.name;
       ok = false;
     }
   }
   if (vec.vec->wr_init == nullptr) {
     if (vec.vec->write != nullptr) {
-      printf("ERROR null wr_init with non-null write %s\n", vec.name);
+      Warning() << "ERROR null wr_init with non-null write %s\n" << vec.name;
       ok = false;
     }
     if (vec.vec->wr_deinit != nullptr) {
-      printf("ERROR null wr_init with non-null wr_deinit %s\n", vec.name);
+      Warning() << "ERROR null wr_init with non-null wr_deinit %s\n" << vec.name;
       ok = false;
     }
   }
 
   if (vec.vec->rd_init != nullptr) {
     if (vec.vec->read == nullptr) {
-      printf("ERROR nonnull rd_init but null read %s\n", vec.name);
+      Warning() << "ERROR nonnull rd_init but null read %s\n" << vec.name;
       ok = false;
     }
     if (vec.vec->rd_deinit == nullptr) {
-      printf("ERROR nonnull rd_init but null rd_deinit %s\n", vec.name);
+      Warning() << "ERROR nonnull rd_init but null rd_deinit %s\n" << vec.name;
       ok = false;
     }
   }
   if (vec.vec->rd_init == nullptr) {
     if (vec.vec->read != nullptr) {
-      printf("ERROR null rd_init with non-null read %s\n", vec.name);
+      Warning() << "ERROR null rd_init with non-null read %s\n" << vec.name;
       ok = false;
     }
     if (vec.vec->rd_deinit != nullptr) {
-      printf("ERROR null rd_init with non-null rd_deinit %s\n", vec.name);
+      Warning() << "ERROR null rd_init with non-null rd_deinit %s\n" << vec.name;
       ok = false;
     }
   }
@@ -1735,7 +1756,7 @@ validate_vec(const vecs_t& vec)
   return ok;
 }
 
-int validate_formats()
+bool validate_formats()
 {
   bool ok = true;
 
@@ -1743,5 +1764,5 @@ int validate_formats()
     ok = validate_vec(vec) && ok;
   }
 
-  return ok? 0 : 1;
+  return ok;
 }